package com.eduagent.xwqeduagent.controller;

import com.eduagent.xwqeduagent.api.SpeechEvaluation.SpeechEvaluationParams;
import com.eduagent.xwqeduagent.api.SpeechEvaluation.SpeechEvaluationService;
import com.eduagent.xwqeduagent.app.student.UniversalLearningAssistant.UniversalLearningAssistant;
import com.eduagent.xwqeduagent.common.BaseResponse;
import com.eduagent.xwqeduagent.common.ResultUtils;
import com.eduagent.xwqeduagent.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * 语音评测控制器
 */
@RestController
@RequestMapping("/speech-evaluation")
@Slf4j
public class SpeechEvaluationController {

    @Autowired
    private SpeechEvaluationService speechEvaluationService;
    
    @Autowired
    private UniversalLearningAssistant universalLearningAssistant;

    /**
     * 使用音频文件进行语音评测
     * 
     * @param file 音频文件
     * @param language 语言类型 (cn_vip/en_vip)
     * @param category 题型 (read_word/read_sentence/read_chapter)
     * @param text 评测文本
     * @param extraAbility 拓展能力，多个值用分号分隔 (multi_dimension/pitch/syll_phone_err_msg)
     * @param group 针对群体 (adult/youth/pupil)
     * @param checkType 评测的打分及检错松严门限 (easy/common/hard)
     * @param grade 学段参数 (junior/middle/senior)
     * @param rst 评测返回结果与分制控制 (entirety/plain)
     * @param iseUnite 返回结果控制 (0/1)
     * @param plev 返回结果详细程度 (0)
     * @param tte 文本编码 (utf-8/gbk)
     * @param ttpSkip 是否跳过ttp (true/false)
     * @param rstcd 返回结果格式 (utf8/gbk)
     * @return 评测结果
     */
    @PostMapping("/evaluate")
    public BaseResponse<String> evaluate(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "language", defaultValue = "cn_vip") String language,
            @RequestParam(value = "category", defaultValue = "read_sentence") String category,
            @RequestParam(value = "text", required = false) String text,
            @RequestParam(value = "extraAbility", required = false) String extraAbility,
            @RequestParam(value = "group", required = false) String group,
            @RequestParam(value = "checkType", required = false) String checkType,
            @RequestParam(value = "grade", required = false) String grade,
            @RequestParam(value = "rst", required = false, defaultValue = "entirety") String rst,
            @RequestParam(value = "iseUnite", required = false, defaultValue = "0") String iseUnite,
            @RequestParam(value = "plev", required = false, defaultValue = "0") String plev,
            @RequestParam(value = "tte", required = false, defaultValue = "utf-8") String tte,
            @RequestParam(value = "ttpSkip", required = false, defaultValue = "true") Boolean ttpSkip,
            @RequestParam(value = "rstcd", required = false, defaultValue = "utf8") String rstcd) {
        
        if (file.isEmpty()) {
            return new BaseResponse<>(ErrorCode.PARAMS_ERROR.getCode(), null, "音频文件不能为空");
        }
        
        // 记录请求参数
        log.info("收到语音评测请求: language={}, category={}, text={}, file={}", 
                language, category, text, file.getOriginalFilename());
        
        // 如果text为空，设置一个默认值
        if (text == null || text.isEmpty()) {
            log.warn("评测文本为空，使用默认文本");
            text = "默认评测文本";
        }
        
        // 根据语言类型设置推荐的配置
        if ("en_vip".equals(language)) {
            log.info("英文评测，使用推荐配置");
            // 英文评测的参数优化
            rst = "entirety";
            iseUnite = "1";
            if (extraAbility == null || extraAbility.isEmpty()) {
                extraAbility = "multi_dimension";
            }
            
            // 确保英文文本不包含无法识别的符号
            text = text.replaceAll("[^a-zA-Z0-9\\s.,?!';:\\-]", "");
        }
        
        // 检查音频文件
        if (!isValidAudioFile(file)) {
            return new BaseResponse<>(ErrorCode.PARAMS_ERROR.getCode(), null, "无效的音频文件格式或内容");
        }
        
        Path tempFilePath = null;
        try {
            // 保存临时文件
            String tempDir = System.getProperty("java.io.tmpdir");
            String fileName = UUID.randomUUID().toString() + getFileExtension(file.getOriginalFilename());
            tempFilePath = Paths.get(tempDir, fileName);
            
            file.transferTo(tempFilePath.toFile());
            log.debug("临时音频文件已保存: {}", tempFilePath);
            
            // 确定音频格式
            String aue = getAueFromFileName(file.getOriginalFilename());
            String auf = "audio/L16;rate=16000";
            
            // 构建评测参数
            SpeechEvaluationParams params = SpeechEvaluationParams.builder()
                    .sub("ise")
                    .ent(language)
                    .category(category)
                    .text(text)
                    .tte("utf-8") // 明确指定UTF-8编码
                    .ttpSkip(true) // 确保始终为true
                    .aue(aue)
                    .auf(auf)
                    .rstcd("utf8") // 使用UTF-8作为结果编码，避免中文乱码
                    .build();
            
            // 添加可选参数
            if (extraAbility != null && !extraAbility.isEmpty()) {
                params.setExtraAbility(extraAbility);
            }
            if (group != null && !group.isEmpty()) {
                params.setGroup(group);
            }
            if (checkType != null && !checkType.isEmpty()) {
                params.setCheckType(checkType);
            }
            if (grade != null && !grade.isEmpty()) {
                params.setGrade(grade);
            }
            
            // 设置结果控制参数
            params.setRst(rst);
            params.setIseUnite(iseUnite);
            params.setPlev(plev);
            
            log.info("开始执行语音评测...");
            // 执行评测
            String result = speechEvaluationService.evaluateFromFile(params, tempFilePath.toString());
            log.info("语音评测完成，结果长度: {} 字符", result != null ? result.length() : 0);
            
            return ResultUtils.success(result);
        } catch (Exception e) {
            // 分类处理不同类型的错误
            if (e.getMessage() != null && e.getMessage().contains("HMAC signature")) {
                log.error("语音评测鉴权失败: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "语音评测鉴权失败，请检查API密钥配置");
            } else if (e.getMessage() != null && e.getMessage().contains("WebSocket")) {
                log.error("WebSocket连接错误: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "WebSocket连接错误: " + e.getMessage());
            } else if (e.getMessage() != null && (e.getMessage().contains("invalid handle") || e.getMessage().contains("10165"))) {
                log.error("语音评测服务处理错误: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "语音评测服务处理错误: 请检查音频格式和文本是否匹配");
            } else {
                log.error("语音评测失败: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "语音评测失败: " + e.getMessage());
            }
        } finally {
            // 清理临时文件
            if (tempFilePath != null) {
                try {
                    Files.deleteIfExists(tempFilePath);
                    log.debug("临时音频文件已删除: {}", tempFilePath);
                } catch (IOException e) {
                    log.warn("删除临时音频文件失败: {}", tempFilePath, e);
                }
            }
        }
    }

    /**
     * 检查音频文件是否有效
     * @param file 音频文件
     * @return 是否有效
     */
    private boolean isValidAudioFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return false;
        }
        
        // 检查文件大小
        if (file.getSize() <= 0 || file.getSize() > 10 * 1024 * 1024) { // 限制10MB
            log.warn("无效的音频文件大小: {} 字节", file.getSize());
            return false;
        }
        
        // 检查文件名后缀
        String fileName = file.getOriginalFilename();
        if (fileName != null) {
            String extension = getFileExtension(fileName).toLowerCase();
            if (!".wav".equals(extension) && !".pcm".equals(extension) && !".mp3".equals(extension)) {
                log.warn("不支持的音频文件格式: {}", extension);
                return false;
            }
        }
        
        // 进一步检查文件内容格式（简单检查，不是全面的）
        try {
            byte[] header = new byte[12];
            file.getInputStream().read(header);
            
            // 检查wav文件头
            if (fileName != null && fileName.toLowerCase().endsWith(".wav")) {
                // WAV文件通常以"RIFF"开头
                if (header.length >= 4 && 
                    header[0] == 'R' && header[1] == 'I' && 
                    header[2] == 'F' && header[3] == 'F') {
                    return true;
                } else {
                    log.warn("无效的WAV文件头");
                    return false;
                }
            }
            
            // 检查MP3文件头
            if (fileName != null && fileName.toLowerCase().endsWith(".mp3")) {
                // MP3文件通常以ID3或者0xFF 0xFB开头
                if (header.length >= 3 && 
                    ((header[0] == 'I' && header[1] == 'D' && header[2] == '3') || 
                     ((header[0] & 0xFF) == 0xFF && (header[1] & 0xE0) == 0xE0))) {
                    return true;
                } else {
                    // MP3文件可能没有ID3头，所以只检查文件扩展名
                    return true;
                }
            }
            
            // 对于PCM文件，我们无法通过文件头确定，只能通过扩展名
            if (fileName != null && fileName.toLowerCase().endsWith(".pcm")) {
                return true;
            }
            
            return false;
        } catch (IOException e) {
            log.error("检查音频文件内容时发生错误", e);
            return false;
        }
    }

    /**
     * 使用音频字节数据进行语音评测
     * 
     * @param data 音频字节数据请求体
     * @param language 语言类型 (cn_vip/en_vip)
     * @param category 题型 (read_word/read_sentence/read_chapter)
     * @param text 评测文本
     * @param aue 音频格式
     * @param extraAbility 拓展能力，多个值用分号分隔 (multi_dimension/pitch/syll_phone_err_msg)
     * @param group 针对群体 (adult/youth/pupil)
     * @param checkType 评测的打分及检错松严门限 (easy/common/hard)
     * @param grade 学段参数 (junior/middle/senior)
     * @param rst 评测返回结果与分制控制 (entirety/plain)
     * @param iseUnite 返回结果控制 (0/1)
     * @param plev 返回结果详细程度 (0)
     * @param tte 文本编码 (utf-8/gbk)
     * @param ttpSkip 是否跳过ttp (true/false)
     * @param rstcd 返回结果格式 (utf8/gbk)
     * @return 评测结果
     */
    @PostMapping("/evaluate-bytes")
    public BaseResponse<String> evaluateBytes(
            @RequestBody byte[] data,
            @RequestParam(value = "language", defaultValue = "cn_vip") String language,
            @RequestParam(value = "category", defaultValue = "read_sentence") String category,
            @RequestParam(value = "text", required = false) String text,
            @RequestParam(value = "aue", defaultValue = "raw") String aue,
            @RequestParam(value = "extraAbility", required = false) String extraAbility,
            @RequestParam(value = "group", required = false) String group,
            @RequestParam(value = "checkType", required = false) String checkType,
            @RequestParam(value = "grade", required = false) String grade,
            @RequestParam(value = "rst", required = false, defaultValue = "entirety") String rst,
            @RequestParam(value = "iseUnite", required = false, defaultValue = "0") String iseUnite,
            @RequestParam(value = "plev", required = false, defaultValue = "0") String plev,
            @RequestParam(value = "tte", required = false, defaultValue = "utf-8") String tte,
            @RequestParam(value = "ttpSkip", required = false, defaultValue = "true") Boolean ttpSkip,
            @RequestParam(value = "rstcd", required = false, defaultValue = "utf8") String rstcd) {
        
        if (data == null || data.length == 0) {
            return new BaseResponse<>(ErrorCode.PARAMS_ERROR.getCode(), null, "音频数据不能为空");
        }
        
        // 记录请求参数
        log.info("收到字节评测请求: language={}, category={}, text={}, dataSize={}", 
                language, category, text, data.length);
        
        // 如果text为空，设置一个默认值
        if (text == null || text.isEmpty()) {
            log.warn("评测文本为空，使用默认文本");
            text = "默认评测文本";
        }
        
        // 检查音频数据
        if (data.length > 10 * 1024 * 1024) { // 限制10MB
            log.warn("音频数据过大: {} 字节", data.length);
            return new BaseResponse<>(ErrorCode.PARAMS_ERROR.getCode(), null, "音频数据过大，请控制在10MB以内");
        }
        
        try {
            // 构建评测参数
            SpeechEvaluationParams params = SpeechEvaluationParams.builder()
                    .sub("ise")
                    .ent(language)
                    .category(category)
                    .text(text) // 原始文本，SpeechEvaluationClient会添加BOM头
                    .tte(tte)
                    .ttpSkip(ttpSkip)
                    .aue(aue)
                    .auf("audio/L16;rate=16000")
                    .rstcd(rstcd)
                    .build();
            
            // 添加可选参数
            if (extraAbility != null && !extraAbility.isEmpty()) {
                params.setExtraAbility(extraAbility);
            }
            if (group != null && !group.isEmpty()) {
                params.setGroup(group);
            }
            if (checkType != null && !checkType.isEmpty()) {
                params.setCheckType(checkType);
            }
            if (grade != null && !grade.isEmpty()) {
                params.setGrade(grade);
            }
            if (rst != null && !rst.isEmpty()) {
                params.setRst(rst);
            }
            if (iseUnite != null && !iseUnite.isEmpty()) {
                params.setIseUnite(iseUnite);
            }
            if (plev != null && !plev.isEmpty()) {
                params.setPlev(plev);
            }
            
            log.info("开始执行字节音频评测...");
            // 执行评测
            String result = speechEvaluationService.evaluate(params, data);
            log.info("字节音频评测完成，结果长度: {} 字符", result != null ? result.length() : 0);
            
            return ResultUtils.success(result);
        } catch (Exception e) {
            // 分类处理不同类型的错误
            if (e.getMessage() != null && e.getMessage().contains("HMAC signature")) {
                log.error("语音评测鉴权失败: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "语音评测鉴权失败，请检查API密钥配置");
            } else if (e.getMessage() != null && e.getMessage().contains("WebSocket")) {
                log.error("WebSocket连接错误: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "WebSocket连接错误: " + e.getMessage());
            } else {
                log.error("语音评测失败: {}", e.getMessage(), e);
                return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "语音评测失败: " + e.getMessage());
            }
        }
    }
    
    /**
     * 使用AI解析语音评测XML结果
     * 
     * @param xmlResult 评测返回的XML结果
     * @param sessionId 会话ID，用于保持对话上下文（可选）
     * @return AI分析结果
     */
    @PostMapping("/analyze")
    public BaseResponse<String> analyzeEvaluationResult(
            @RequestParam("xmlResult") String xmlResult,
            @RequestParam(value = "sessionId", required = false) String sessionId) {
        
        if (xmlResult == null || xmlResult.isEmpty()) {
            return new BaseResponse<>(ErrorCode.PARAMS_ERROR.getCode(), null, "评测结果XML不能为空");
        }
        
        try {
            // 如果未提供会话ID，生成一个新的
            String effectiveSessionId = sessionId;
            if (effectiveSessionId == null || effectiveSessionId.isEmpty()) {
                effectiveSessionId = UUID.randomUUID().toString();
            }
            
            // 调用AI解析XML结果
            String analysisResult = universalLearningAssistant.VoiceEvaluationAndAnalysis(xmlResult, effectiveSessionId);
            
            return ResultUtils.success(analysisResult);
        } catch (Exception e) {
            log.error("AI解析语音评测结果失败", e);
            return new BaseResponse<>(ErrorCode.SYSTEM_ERROR.getCode(), null, "AI解析失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件扩展名
     * @param fileName 文件名
     * @return 文件扩展名（包含"."）
     */
    private String getFileExtension(String fileName) {
        if (fileName == null) {
            return "";
        }
        int lastDotIndex = fileName.lastIndexOf(".");
        if (lastDotIndex >= 0) {
            return fileName.substring(lastDotIndex);
        }
        return "";
    }
    
    /**
     * 根据文件名判断音频格式
     * @param fileName 文件名
     * @return 音频格式编码
     */
    private String getAueFromFileName(String fileName) {
        if (fileName == null) {
            return "raw"; // 默认为raw格式
        }
        
        String lowercaseFileName = fileName.toLowerCase();
        if (lowercaseFileName.endsWith(".mp3")) {
            return "lame"; // mp3格式
        } else if (lowercaseFileName.endsWith(".wav") || lowercaseFileName.endsWith(".pcm")) {
            return "raw"; // wav/pcm格式
        } else {
            return "raw"; // 默认为raw格式
        }
    }

    /**
     * 检查英文评测的题型是否合适
     * 
     * @param category 题型
     * @return 是否合适
     */
    private boolean isValidEnglishCategory(String category) {
        if (category == null || category.isEmpty()) {
            return false;
        }
        String lowerCategory = category.toLowerCase();
        return lowerCategory.equals("read_word") || lowerCategory.equals("read_sentence") || lowerCategory.equals("read_chapter");
    }
} 